// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <PyView2DAttributes.h>
#include <ObserverToCallback.h>
#include <stdio.h>
#include <Py2and3Support.h>

// ****************************************************************************
// Module: PyView2DAttributes
//
// Purpose:
//   This class contains the 2d view attributes.
//
// Note:       Autogenerated by xml2python. Do not modify by hand!
//
// Programmer: xml2python
// Creation:   omitted
//
// ****************************************************************************

//
// This struct contains the Python type information and a View2DAttributes.
//
struct View2DAttributesObject
{
    PyObject_HEAD
    View2DAttributes *data;
    bool        owns;
    PyObject   *parent;
};

//
// Internal prototypes
//
static PyObject *NewView2DAttributes(int);
std::string
PyView2DAttributes_ToString(const View2DAttributes *atts, const char *prefix)
{
    std::string str;
    char tmpStr[1000];

    {   const double *windowCoords = atts->GetWindowCoords();
        snprintf(tmpStr, 1000, "%swindowCoords = (", prefix);
        str += tmpStr;
        for(int i = 0; i < 4; ++i)
        {
            snprintf(tmpStr, 1000, "%g", windowCoords[i]);
            str += tmpStr;
            if(i < 3)
            {
                snprintf(tmpStr, 1000, ", ");
                str += tmpStr;
            }
        }
        snprintf(tmpStr, 1000, ")\n");
        str += tmpStr;
    }
    {   const double *viewportCoords = atts->GetViewportCoords();
        snprintf(tmpStr, 1000, "%sviewportCoords = (", prefix);
        str += tmpStr;
        for(int i = 0; i < 4; ++i)
        {
            snprintf(tmpStr, 1000, "%g", viewportCoords[i]);
            str += tmpStr;
            if(i < 3)
            {
                snprintf(tmpStr, 1000, ", ");
                str += tmpStr;
            }
        }
        snprintf(tmpStr, 1000, ")\n");
        str += tmpStr;
    }
    const char *fullFrameActivationMode_names = "On, Off, Auto";
    switch (atts->GetFullFrameActivationMode())
    {
      case View2DAttributes::On:
          snprintf(tmpStr, 1000, "%sfullFrameActivationMode = %sOn  # %s\n", prefix, prefix, fullFrameActivationMode_names);
          str += tmpStr;
          break;
      case View2DAttributes::Off:
          snprintf(tmpStr, 1000, "%sfullFrameActivationMode = %sOff  # %s\n", prefix, prefix, fullFrameActivationMode_names);
          str += tmpStr;
          break;
      case View2DAttributes::Auto:
          snprintf(tmpStr, 1000, "%sfullFrameActivationMode = %sAuto  # %s\n", prefix, prefix, fullFrameActivationMode_names);
          str += tmpStr;
          break;
      default:
          break;
    }

    snprintf(tmpStr, 1000, "%sfullFrameAutoThreshold = %g\n", prefix, atts->GetFullFrameAutoThreshold());
    str += tmpStr;
    const char *xScale_values[] = {"LINEAR", "LOG"};
    snprintf(tmpStr, 1000, "%sxScale = %s%s  # LINEAR, LOG\n", prefix, prefix, xScale_values[atts->GetXScale()]);
    str += tmpStr;
    const char *yScale_values[] = {"LINEAR", "LOG"};
    snprintf(tmpStr, 1000, "%syScale = %s%s  # LINEAR, LOG\n", prefix, prefix, yScale_values[atts->GetYScale()]);
    str += tmpStr;
    if(atts->GetWindowValid())
        snprintf(tmpStr, 1000, "%swindowValid = 1\n", prefix);
    else
        snprintf(tmpStr, 1000, "%swindowValid = 0\n", prefix);
    str += tmpStr;
    return str;
}

static PyObject *
View2DAttributes_Notify(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    obj->data->Notify();
    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_SetWindowCoords(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    double *dvals = obj->data->GetWindowCoords();
    if(!PyArg_ParseTuple(args, "dddd", &dvals[0], &dvals[1], &dvals[2], &dvals[3]))
    {
        PyObject     *tuple;
        if(!PyArg_ParseTuple(args, "O", &tuple))
            return NULL;

        if(PyTuple_Check(tuple))
        {
            if(PyTuple_Size(tuple) != 4)
                return NULL;

            PyErr_Clear();
            for(int i = 0; i < PyTuple_Size(tuple); ++i)
            {
                PyObject *item = PyTuple_GET_ITEM(tuple, i);
                if(PyFloat_Check(item))
                    dvals[i] = PyFloat_AS_DOUBLE(item);
                else if(PyInt_Check(item))
                    dvals[i] = double(PyInt_AS_LONG(item));
                else if(PyLong_Check(item))
                    dvals[i] = PyLong_AsDouble(item);
                else
                    dvals[i] = 0.;
            }
        }
        else
            return NULL;
    }

    // Mark the windowCoords in the object as modified.
    obj->data->SelectWindowCoords();

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetWindowCoords(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    // Allocate a tuple the with enough entries to hold the windowCoords.
    PyObject *retval = PyTuple_New(4);
    const double *windowCoords = obj->data->GetWindowCoords();
    for(int i = 0; i < 4; ++i)
        PyTuple_SET_ITEM(retval, i, PyFloat_FromDouble(windowCoords[i]));
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetViewportCoords(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    double *dvals = obj->data->GetViewportCoords();
    if(!PyArg_ParseTuple(args, "dddd", &dvals[0], &dvals[1], &dvals[2], &dvals[3]))
    {
        PyObject     *tuple;
        if(!PyArg_ParseTuple(args, "O", &tuple))
            return NULL;

        if(PyTuple_Check(tuple))
        {
            if(PyTuple_Size(tuple) != 4)
                return NULL;

            PyErr_Clear();
            for(int i = 0; i < PyTuple_Size(tuple); ++i)
            {
                PyObject *item = PyTuple_GET_ITEM(tuple, i);
                if(PyFloat_Check(item))
                    dvals[i] = PyFloat_AS_DOUBLE(item);
                else if(PyInt_Check(item))
                    dvals[i] = double(PyInt_AS_LONG(item));
                else if(PyLong_Check(item))
                    dvals[i] = PyLong_AsDouble(item);
                else
                    dvals[i] = 0.;
            }
        }
        else
            return NULL;
    }

    // Mark the viewportCoords in the object as modified.
    obj->data->SelectViewportCoords();

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetViewportCoords(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    // Allocate a tuple the with enough entries to hold the viewportCoords.
    PyObject *retval = PyTuple_New(4);
    const double *viewportCoords = obj->data->GetViewportCoords();
    for(int i = 0; i < 4; ++i)
        PyTuple_SET_ITEM(retval, i, PyFloat_FromDouble(viewportCoords[i]));
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetFullFrameActivationMode(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    int ival;
    if(!PyArg_ParseTuple(args, "i", &ival))
        return NULL;

    // Set the fullFrameActivationMode in the object.
    if(ival >= 0 && ival < 3)
        obj->data->SetFullFrameActivationMode(View2DAttributes::TriStateMode(ival));
    else
    {
        fprintf(stderr, "An invalid fullFrameActivationMode value was given. "
                        "Valid values are in the range of [0,2]. "
                        "You can also use the following names: "
                        "On, Off, Auto.");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetFullFrameActivationMode(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    PyObject *retval = PyInt_FromLong(long(obj->data->GetFullFrameActivationMode()));
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetFullFrameAutoThreshold(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    double dval;
    if(!PyArg_ParseTuple(args, "d", &dval))
        return NULL;

    // Set the fullFrameAutoThreshold in the object.
    obj->data->SetFullFrameAutoThreshold(dval);

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetFullFrameAutoThreshold(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    PyObject *retval = PyFloat_FromDouble(obj->data->GetFullFrameAutoThreshold());
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetXScale(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    int ival;
    if(!PyArg_ParseTuple(args, "i", &ival))
        return NULL;

    // Set the xScale in the object.
    if(ival >= 0 && ival <= 1)
        obj->data->SetXScale(ival);
    else
    {
        fprintf(stderr, "An invalid  value was given. "
                        "Valid values are in the range of [0,1]. "
                        "You can also use the following names: "
                        "\"LINEAR\", \"LOG\"\n");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetXScale(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    PyObject *retval = PyInt_FromLong(long(obj->data->GetXScale()));
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetYScale(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    int ival;
    if(!PyArg_ParseTuple(args, "i", &ival))
        return NULL;

    // Set the yScale in the object.
    if(ival >= 0 && ival <= 1)
        obj->data->SetYScale(ival);
    else
    {
        fprintf(stderr, "An invalid  value was given. "
                        "Valid values are in the range of [0,1]. "
                        "You can also use the following names: "
                        "\"LINEAR\", \"LOG\"\n");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetYScale(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    PyObject *retval = PyInt_FromLong(long(obj->data->GetYScale()));
    return retval;
}

/*static*/ PyObject *
View2DAttributes_SetWindowValid(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;

    int ival;
    if(!PyArg_ParseTuple(args, "i", &ival))
        return NULL;

    // Set the windowValid in the object.
    obj->data->SetWindowValid(ival != 0);

    Py_INCREF(Py_None);
    return Py_None;
}

/*static*/ PyObject *
View2DAttributes_GetWindowValid(PyObject *self, PyObject *args)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)self;
    PyObject *retval = PyInt_FromLong(obj->data->GetWindowValid()?1L:0L);
    return retval;
}


static PyObject *
View2DAttributes_Add(PyObject *v, PyObject *w)
{
    bool arg1isObject = PyView2DAttributes_Check(v);
    bool arg2isObject = PyView2DAttributes_Check(w);
    if(!arg1isObject || !arg2isObject)
    {
        cerr << "View2DAttributes_Add: One or more arguments are not View2DAttributes!" << endl;
        return NULL;
    }


    PyObject *retval = NewView2DAttributes(0);
    View2DAttributes *c = PyView2DAttributes_FromPyObject(retval);
    View2DAttributes *a = ((View2DAttributesObject *)v)->data;
    View2DAttributes *b = ((View2DAttributesObject *)w)->data;


    c->GetWindowCoords()[0] = a->GetWindowCoords()[0] + b->GetWindowCoords()[0];
    c->GetWindowCoords()[1] = a->GetWindowCoords()[1] + b->GetWindowCoords()[1];
    c->GetWindowCoords()[2] = a->GetWindowCoords()[2] + b->GetWindowCoords()[2];
    c->GetWindowCoords()[3] = a->GetWindowCoords()[3] + b->GetWindowCoords()[3];


    c->GetViewportCoords()[0] = a->GetViewportCoords()[0] + b->GetViewportCoords()[0];
    c->GetViewportCoords()[1] = a->GetViewportCoords()[1] + b->GetViewportCoords()[1];
    c->GetViewportCoords()[2] = a->GetViewportCoords()[2] + b->GetViewportCoords()[2];
    c->GetViewportCoords()[3] = a->GetViewportCoords()[3] + b->GetViewportCoords()[3];


    if(a->GetFullFrameAutoThreshold() < b->GetFullFrameAutoThreshold())
        c->SetFullFrameAutoThreshold(a->GetFullFrameAutoThreshold());
    else
        c->SetFullFrameAutoThreshold(b->GetFullFrameAutoThreshold());


    if(a->GetFullFrameActivationMode() == View2DAttributes::On &&
       b->GetFullFrameActivationMode() == View2DAttributes::On)
    {
        c->SetFullFrameActivationMode(View2DAttributes::On);
    }
    else if(a->GetFullFrameActivationMode() == View2DAttributes::Off &&
       b->GetFullFrameActivationMode() == View2DAttributes::Off)
    {
        c->SetFullFrameActivationMode(View2DAttributes::Off);
    }
    else
        c->SetFullFrameActivationMode(View2DAttributes::Auto);

    return retval;
}

static PyObject *
View2DAttributes_Mul(PyObject *v, PyObject *w)
{
    PyObject *retval = NewView2DAttributes(0);
    View2DAttributes *c = PyView2DAttributes_FromPyObject(retval);


    View2DAttributes *a;
    double val = 1.;
    bool arg1isObject = PyView2DAttributes_Check(v);
    bool arg2isObject = PyView2DAttributes_Check(w);


    if(arg1isObject && arg2isObject)
    {
        PyErr_SetString(PyExc_TypeError,
                    "View2DAttributes_mult: Both  arguments are View2DAttributes!"
                    " Expected one View2DAttributes object and one numeric argument.");
        return NULL;
    }
    else
    {
        PyObject *num;


        if(arg1isObject)
        {
            a = ((View2DAttributesObject *)v)->data;
            num = w;
        }
        else
        {
            a = ((View2DAttributesObject *)w)->data;
            num = v;
        }


        if(PyFloat_Check(num))
            val = PyFloat_AS_DOUBLE(num);
        else if(PyInt_Check(num))
            val = double(PyInt_AS_LONG(num));
        else if(PyLong_Check(num))
            val = PyLong_AsDouble(num);
        else
        {
            PyErr_SetString(PyExc_TypeError,
                        "View2DAttributes_mult: Expected numeric argument is not a number!"
                        " Expected one View2DAttributes object and one numeric argument.");
            return NULL;
        }


        c->GetWindowCoords()[0] = a->GetWindowCoords()[0] * val;
        c->GetWindowCoords()[1] = a->GetWindowCoords()[1] * val;
        c->GetWindowCoords()[2] = a->GetWindowCoords()[2] * val;
        c->GetWindowCoords()[3] = a->GetWindowCoords()[3] * val;


        c->GetViewportCoords()[0] = a->GetViewportCoords()[0] * val;
        c->GetViewportCoords()[1] = a->GetViewportCoords()[1] * val;
        c->GetViewportCoords()[2] = a->GetViewportCoords()[2] * val;
        c->GetViewportCoords()[3] = a->GetViewportCoords()[3] * val;


        c->SetFullFrameAutoThreshold(a->GetFullFrameAutoThreshold() * val);
        c->SetFullFrameActivationMode(a->GetFullFrameActivationMode());
    }

    return retval;
}


PyMethodDef PyView2DAttributes_methods[VIEW2DATTRIBUTES_NMETH] = {
    {"Notify", View2DAttributes_Notify, METH_VARARGS},
    {"SetWindowCoords", View2DAttributes_SetWindowCoords, METH_VARARGS},
    {"GetWindowCoords", View2DAttributes_GetWindowCoords, METH_VARARGS},
    {"SetViewportCoords", View2DAttributes_SetViewportCoords, METH_VARARGS},
    {"GetViewportCoords", View2DAttributes_GetViewportCoords, METH_VARARGS},
    {"SetFullFrameActivationMode", View2DAttributes_SetFullFrameActivationMode, METH_VARARGS},
    {"GetFullFrameActivationMode", View2DAttributes_GetFullFrameActivationMode, METH_VARARGS},
    {"SetFullFrameAutoThreshold", View2DAttributes_SetFullFrameAutoThreshold, METH_VARARGS},
    {"GetFullFrameAutoThreshold", View2DAttributes_GetFullFrameAutoThreshold, METH_VARARGS},
    {"SetXScale", View2DAttributes_SetXScale, METH_VARARGS},
    {"GetXScale", View2DAttributes_GetXScale, METH_VARARGS},
    {"SetYScale", View2DAttributes_SetYScale, METH_VARARGS},
    {"GetYScale", View2DAttributes_GetYScale, METH_VARARGS},
    {"SetWindowValid", View2DAttributes_SetWindowValid, METH_VARARGS},
    {"GetWindowValid", View2DAttributes_GetWindowValid, METH_VARARGS},
    {"Add", View2DAttributes_Add, METH_VARARGS},
    {"Mul", View2DAttributes_Mul, METH_VARARGS},
    {NULL, NULL}
};

//
// Type functions
//

static void
View2DAttributes_dealloc(PyObject *v)
{
   View2DAttributesObject *obj = (View2DAttributesObject *)v;
   if(obj->parent != 0)
       Py_DECREF(obj->parent);
   if(obj->owns)
       delete obj->data;
}

static PyObject *View2DAttributes_richcompare(PyObject *self, PyObject *other, int op);
PyObject *
PyView2DAttributes_getattr(PyObject *self, char *name)
{
    if(strcmp(name, "windowCoords") == 0)
        return View2DAttributes_GetWindowCoords(self, NULL);
    if(strcmp(name, "viewportCoords") == 0)
        return View2DAttributes_GetViewportCoords(self, NULL);
    if(strcmp(name, "fullFrameActivationMode") == 0)
        return View2DAttributes_GetFullFrameActivationMode(self, NULL);
    if(strcmp(name, "On") == 0)
        return PyInt_FromLong(long(View2DAttributes::On));
    if(strcmp(name, "Off") == 0)
        return PyInt_FromLong(long(View2DAttributes::Off));
    if(strcmp(name, "Auto") == 0)
        return PyInt_FromLong(long(View2DAttributes::Auto));

    if(strcmp(name, "fullFrameAutoThreshold") == 0)
        return View2DAttributes_GetFullFrameAutoThreshold(self, NULL);
    if(strcmp(name, "xScale") == 0)
        return View2DAttributes_GetXScale(self, NULL);
    if(strcmp(name, "LINEAR") == 0)
        return PyInt_FromLong(long(0));
    else if(strcmp(name, "LOG") == 0)
        return PyInt_FromLong(long(1));

    if(strcmp(name, "yScale") == 0)
        return View2DAttributes_GetYScale(self, NULL);
    if(strcmp(name, "LINEAR") == 0)
        return PyInt_FromLong(long(0));
    else if(strcmp(name, "LOG") == 0)
        return PyInt_FromLong(long(1));

    if(strcmp(name, "windowValid") == 0)
        return View2DAttributes_GetWindowValid(self, NULL);

    // Add a __dict__ answer so that dir() works
    if (!strcmp(name, "__dict__"))
    {
        PyObject *result = PyDict_New();
        for (int i = 0; PyView2DAttributes_methods[i].ml_meth; i++)
            PyDict_SetItem(result,
                PyString_FromString(PyView2DAttributes_methods[i].ml_name),
                PyString_FromString(PyView2DAttributes_methods[i].ml_name));
        return result;
    }

    return Py_FindMethod(PyView2DAttributes_methods, self, name);
}

int
PyView2DAttributes_setattr(PyObject *self, char *name, PyObject *args)
{
    // Create a tuple to contain the arguments since all of the Set
    // functions expect a tuple.
    PyObject *tuple = PyTuple_New(1);
    PyTuple_SET_ITEM(tuple, 0, args);
    Py_INCREF(args);
    PyObject *obj = NULL;

    if(strcmp(name, "windowCoords") == 0)
        obj = View2DAttributes_SetWindowCoords(self, tuple);
    else if(strcmp(name, "viewportCoords") == 0)
        obj = View2DAttributes_SetViewportCoords(self, tuple);
    else if(strcmp(name, "fullFrameActivationMode") == 0)
        obj = View2DAttributes_SetFullFrameActivationMode(self, tuple);
    else if(strcmp(name, "fullFrameAutoThreshold") == 0)
        obj = View2DAttributes_SetFullFrameAutoThreshold(self, tuple);
    else if(strcmp(name, "xScale") == 0)
        obj = View2DAttributes_SetXScale(self, tuple);
    else if(strcmp(name, "yScale") == 0)
        obj = View2DAttributes_SetYScale(self, tuple);
    else if(strcmp(name, "windowValid") == 0)
        obj = View2DAttributes_SetWindowValid(self, tuple);

    if(obj != NULL)
        Py_DECREF(obj);

    Py_DECREF(tuple);
    if( obj == NULL)
        PyErr_Format(PyExc_RuntimeError, "Unable to set unknown attribute: '%s'", name);
    return (obj != NULL) ? 0 : -1;
}

static int
View2DAttributes_print(PyObject *v, FILE *fp, int flags)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)v;
    fprintf(fp, "%s", PyView2DAttributes_ToString(obj->data, "").c_str());
    return 0;
}

PyObject *
View2DAttributes_str(PyObject *v)
{
    View2DAttributesObject *obj = (View2DAttributesObject *)v;
    return PyString_FromString(PyView2DAttributes_ToString(obj->data,"").c_str());
}



/*
PyNumberMethods struct differs between Python 2 and Python 3

// Good ref on python 2 and 3 changes for PyNumberMethods
// https://py3c.readthedocs.io/en/latest/ext-types.html#pynumbermethods

// PYTHON 2 STRUCT FOR PyNumberMethods

typedef struct {
     binaryfunc nb_add;
     binaryfunc nb_subtract;
     binaryfunc nb_multiply;
     binaryfunc nb_divide;  // MISSING IN PYTHON 3
     binaryfunc nb_remainder;
     binaryfunc nb_divmod;
     ternaryfunc nb_power;
     unaryfunc nb_negative;
     unaryfunc nb_positive;
     unaryfunc nb_absolute;
     inquiry nb_nonzero;       // Used by PyObject_IsTrue 
     unaryfunc nb_invert;
     binaryfunc nb_lshift;
     binaryfunc nb_rshift;
     binaryfunc nb_and;
     binaryfunc nb_xor;
     binaryfunc nb_or;
     coercion nb_coerce;     // MISSING IN PYTHON 3   // Used by the coerce() function 
     unaryfunc nb_int;
     unaryfunc nb_long;   // MUST BE NULL IN PYTHON 3
     unaryfunc nb_float;
     unaryfunc nb_oct;    // MISSING IN PYTHON 3
     unaryfunc nb_hex;    // MISSING IN PYTHON 3

     // Added in release 2.0 
     binaryfunc nb_inplace_add;
     binaryfunc nb_inplace_subtract;
     binaryfunc nb_inplace_multiply;
     binaryfunc nb_inplace_divide;  // MISSING IN PYTHON 3
     binaryfunc nb_inplace_remainder;
     ternaryfunc nb_inplace_power;
     binaryfunc nb_inplace_lshift;
     binaryfunc nb_inplace_rshift;
     binaryfunc nb_inplace_and;
     binaryfunc nb_inplace_xor;
     binaryfunc nb_inplace_or;

     // Added in release 2.2 
     binaryfunc nb_floor_divide;
     binaryfunc nb_true_divide;
     binaryfunc nb_inplace_floor_divide;
     binaryfunc nb_inplace_true_divide;

     // Added in release 2.5 
     unaryfunc nb_index;
} PyNumberMethods;

// PYTHON 3 STRUCT FOR PyNumberMethods

typedef struct {
     binaryfunc nb_add;
     binaryfunc nb_subtract;
     binaryfunc nb_multiply;
     binaryfunc nb_remainder;
     binaryfunc nb_divmod;
     ternaryfunc nb_power;
     unaryfunc nb_negative;
     unaryfunc nb_positive;
     unaryfunc nb_absolute;
     inquiry nb_bool;
     unaryfunc nb_invert;
     binaryfunc nb_lshift;
     binaryfunc nb_rshift;
     binaryfunc nb_and;
     binaryfunc nb_xor;
     binaryfunc nb_or;
     unaryfunc nb_int;
     void *nb_reserved;
     unaryfunc nb_float;

     binaryfunc nb_inplace_add;
     binaryfunc nb_inplace_subtract;
     binaryfunc nb_inplace_multiply;
     binaryfunc nb_inplace_remainder;
     ternaryfunc nb_inplace_power;
     binaryfunc nb_inplace_lshift;
     binaryfunc nb_inplace_rshift;
     binaryfunc nb_inplace_and;
     binaryfunc nb_inplace_xor;
     binaryfunc nb_inplace_or;

     binaryfunc nb_floor_divide;
     binaryfunc nb_true_divide;
     binaryfunc nb_inplace_floor_divide;
     binaryfunc nb_inplace_true_divide;

     unaryfunc nb_index;

     binaryfunc nb_matrix_multiply; // MISSING IN PYTHON 2
     binaryfunc nb_inplace_matrix_multiply; // MISSING IN PYTHON 2
} PyNumberMethods;

*/

//
// The type description structure
//
static PyNumberMethods View2DAttributes_as_number = {
    (binaryfunc)View2DAttributes_Add, /*nb_add*/
    (binaryfunc)0, /*nb_subtract*/
    (binaryfunc)View2DAttributes_Mul, /*nb_multiply*/
#if !defined(IS_PY3K)
// PYTHON 2 ONLY
    (binaryfunc)0,     /*nb_divide*/ // MISSING IN PYTHON 3
#endif
    (binaryfunc)0,     /*nb_remainder*/
    (binaryfunc)0,     /*nb_divmod*/
    (ternaryfunc)0,    /*nb_power*/
    (unaryfunc)0,     /*nb_negative*/
    (unaryfunc)0,     /*nb_positive*/
    (unaryfunc)0,     /*nb_absolute*/
    (inquiry)0,       /*nb_bool*/
    (unaryfunc)0,     /*nb_invert*/
    (binaryfunc)0,    /*nb_lshift*/
    (binaryfunc)0,    /*nb_rshift*/
    (binaryfunc)0,    /*nb_and*/
    (binaryfunc)0,    /*nb_xor*/
    (binaryfunc)0,    /*nb_or*/
#if !defined(IS_PY3K)
// PYTHON 2 ONLY
    (coercion)0,      /*nb_coerce*/ // MISSING IN PYTHON 3
#endif
    (unaryfunc)0,     /*nb_int*/
    0,                /*nb_reserved*/
    (unaryfunc)0,     /*nb_float*/
#if !defined(IS_PY3K)
// PYTHON 2 ONLY
    (unaryfunc)0,  /*nb_oct*/    // MISSING IN PYTHON 3
// PYTHON 2 ONLY
    (unaryfunc)0, /*nb_hex */    // MISSING IN PYTHON 3
#endif
    0,            /*nb_inplace_add*/
    0,            /*nb_inplace_subtract*/
    0,            /*nb_inplace_multiply*/
#if !defined(IS_PY3K)
// PYTHON 2 ONLY
    0,            /* nb_inplace_divide */ // MISSING IN PYTHON 3
#endif
    0,            /*nb_inplace_remainder*/
    0,            /*nb_inplace_power*/
    0,            /*nb_inplace_lshift*/
    0,            /*nb_inplace_rshift*/
    0,            /*nb_inplace_and*/
    0,            /*nb_inplace_xor*/
    0,            /*nb_inplace_or*/
    (binaryfunc)0, /*nb_floor_divide;*/
    (binaryfunc)0, /*nb_true_divide;*/
    (binaryfunc)0, /*nb_inplace_floor_divide;*/
    (binaryfunc)0, /*nb_inplace_true_divide;*/
    (unaryfunc)0, /*nb_index;*/
#if defined(IS_PY3K)
// PYTHON3 ONLY
    (binaryfunc)0, /*nb_matrix_multiply;*/
    (binaryfunc)0 /*nb_inplace_matrix_multiply;*/
#endif
};

//
// The doc string for the class.
//
#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 5)
static const char *View2DAttributes_Purpose = "This class contains the 2d view attributes.";
#else
static char *View2DAttributes_Purpose = "This class contains the 2d view attributes.";
#endif

//
// The type description structure
//
//

//         VISIT_PY_TYPE_OBJ( VPY_TYPE,
//                            VPY_NAME,
//                            VPY_OBJECT,
//                            VPY_DEALLOC,
//                            VPY_PRINT,
//                            VPY_GETATTR,
//                            VPY_SETATTR,
//                            VPY_STR,
//                            VPY_PURPOSE,
//                            VPY_RICHCOMP,
//                            VPY_AS_NUMBER)

VISIT_PY_TYPE_OBJ(View2DAttributesType,          \
                  "View2DAttributes",            \
                  View2DAttributesObject,        \
                  View2DAttributes_dealloc,      \
                  View2DAttributes_print,        \
                  PyView2DAttributes_getattr,    \
                  PyView2DAttributes_setattr,    \
                  View2DAttributes_str,          \
                  View2DAttributes_Purpose,      \
                  View2DAttributes_richcompare,  \
                  &View2DAttributes_as_number);


static PyObject *
View2DAttributes_richcompare(PyObject *self, PyObject *other, int op)
{
    // only compare against the same type 
    if ( Py_TYPE(self) == Py_TYPE(other) 
         && Py_TYPE(self) == &View2DAttributesType)
    {
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *res = NULL;
    View2DAttributes *a = ((View2DAttributesObject *)self)->data;
    View2DAttributes *b = ((View2DAttributesObject *)other)->data;

    switch (op)
    {
       case Py_EQ:
           res = (*a == *b) ? Py_True : Py_False;
           break;
       case Py_NE:
           res = (*a != *b) ? Py_True : Py_False;
           break;
       default:
           res = Py_NotImplemented;
           break;
    }

    Py_INCREF(res);
    return res;
}

//
// Helper functions for object allocation.
//

static View2DAttributes *defaultAtts = 0;
static View2DAttributes *currentAtts = 0;

static PyObject *
NewView2DAttributes(int useCurrent)
{
    View2DAttributesObject *newObject;
    newObject = PyObject_NEW(View2DAttributesObject, &View2DAttributesType);
    if(newObject == NULL)
        return NULL;
    if(useCurrent && currentAtts != 0)
        newObject->data = new View2DAttributes(*currentAtts);
    else if(defaultAtts != 0)
        newObject->data = new View2DAttributes(*defaultAtts);
    else
        newObject->data = new View2DAttributes;
    newObject->owns = true;
    newObject->parent = 0;
    return (PyObject *)newObject;
}

static PyObject *
WrapView2DAttributes(const View2DAttributes *attr)
{
    View2DAttributesObject *newObject;
    newObject = PyObject_NEW(View2DAttributesObject, &View2DAttributesType);
    if(newObject == NULL)
        return NULL;
    newObject->data = (View2DAttributes *)attr;
    newObject->owns = false;
    newObject->parent = 0;
    return (PyObject *)newObject;
}

///////////////////////////////////////////////////////////////////////////////
//
// Interface that is exposed to the VisIt module.
//
///////////////////////////////////////////////////////////////////////////////

PyObject *
View2DAttributes_new(PyObject *self, PyObject *args)
{
    int useCurrent = 0;
    if (!PyArg_ParseTuple(args, "i", &useCurrent))
    {
        if (!PyArg_ParseTuple(args, ""))
            return NULL;
        else
            PyErr_Clear();
    }

    return (PyObject *)NewView2DAttributes(useCurrent);
}

//
// Plugin method table. These methods are added to the visitmodule's methods.
//
static PyMethodDef View2DAttributesMethods[] = {
    {"View2DAttributes", View2DAttributes_new, METH_VARARGS},
    {NULL,      NULL}        /* Sentinel */
};

static Observer *View2DAttributesObserver = 0;

std::string
PyView2DAttributes_GetLogString()
{
    std::string s("View2DAtts = View2DAttributes()\n");
    if(currentAtts != 0)
        s += PyView2DAttributes_ToString(currentAtts, "View2DAtts.");
    return s;
}

static void
PyView2DAttributes_CallLogRoutine(Subject *subj, void *data)
{
    typedef void (*logCallback)(const std::string &);
    logCallback cb = (logCallback)data;

    if(cb != 0)
    {
        std::string s("View2DAtts = View2DAttributes()\n");
        s += PyView2DAttributes_ToString(currentAtts, "View2DAtts.");
        cb(s);
    }
}

void
PyView2DAttributes_StartUp(View2DAttributes *subj, void *data)
{
    if(subj == 0)
        return;

    currentAtts = subj;
    PyView2DAttributes_SetDefaults(subj);

    //
    // Create the observer that will be notified when the attributes change.
    //
    if(View2DAttributesObserver == 0)
    {
        View2DAttributesObserver = new ObserverToCallback(subj,
            PyView2DAttributes_CallLogRoutine, (void *)data);
    }

}

void
PyView2DAttributes_CloseDown()
{
    delete defaultAtts;
    defaultAtts = 0;
    delete View2DAttributesObserver;
    View2DAttributesObserver = 0;
}

PyMethodDef *
PyView2DAttributes_GetMethodTable(int *nMethods)
{
    *nMethods = 1;
    return View2DAttributesMethods;
}

bool
PyView2DAttributes_Check(PyObject *obj)
{
    return (obj->ob_type == &View2DAttributesType);
}

View2DAttributes *
PyView2DAttributes_FromPyObject(PyObject *obj)
{
    View2DAttributesObject *obj2 = (View2DAttributesObject *)obj;
    return obj2->data;
}

PyObject *
PyView2DAttributes_New()
{
    return NewView2DAttributes(0);
}

PyObject *
PyView2DAttributes_Wrap(const View2DAttributes *attr)
{
    return WrapView2DAttributes(attr);
}

void
PyView2DAttributes_SetParent(PyObject *obj, PyObject *parent)
{
    View2DAttributesObject *obj2 = (View2DAttributesObject *)obj;
    obj2->parent = parent;
}

void
PyView2DAttributes_SetDefaults(const View2DAttributes *atts)
{
    if(defaultAtts)
        delete defaultAtts;

    defaultAtts = new View2DAttributes(*atts);
}

